﻿#region Using directives

using System.Data;
using System.IO;
using System.Security.Cryptography;
using System.Security;

#endregion

namespace OpenComposite.Base
{
    /// <summary>
    /// Store and retrieve user settings;
    /// </summary>
    public class UserSettings 
    {
        private DataSet m_data;
        private DataTable m_table;
        private string m_fileName;
        private bool m_autosave = true;

        /// <summary>
        /// Clear all settings.
        /// </summary>
        public void ClearSettings()
        {
            m_table.Rows.Clear();
        }

        /// <summary>
        /// Put setting to file.
        /// </summary>
        /// <param name="fileName">Filename.</param>
        /// <param name="property">Property name.</param>
        /// <param name="value">Property value.</param>
        public void PutSetting(string property, string value)
        {
            DataRow[] rows = m_table.Select("property = '" + property + "'");
            if (rows.Length > 0)
                rows[0]["value"] = value;
            else
            {
                DataRow r = m_table.NewRow();
                r["property"] = property;
                r["value"] = value;
                m_table.Rows.Add(r);
            }

            if(m_autosave)
                SaveSettings();
        }

        /// <summary>
        /// Get the value of a property.
        /// </summary>
        /// <param name="property">Property name.</param>
        /// <returns>Returns the value as string.</returns>
        public string GetSetting(string property)
        {
            string value = "";
            DataRow[] rows = m_table.Select("property = '" + property + "'");
            if (rows.Length > 0)
                value = rows[0]["value"].ToString();

            return value;
        }
        
        /// <summary>
        /// Load Settings from file.
        /// </summary>
        public void LoadSettings(string fileName)
        {
            m_fileName = fileName;

            if (File.Exists(fileName))
            {
                try
                {
					m_data = loadEncryptedFile(m_fileName); //.ReadXml(m_fileName);
                }
                catch { }
            }

            if(m_data.DataSetName == "NewDataSet")
                m_data.DataSetName = "UserSettings";

            if(m_data.Tables.Count == 0)
                m_data.Tables.Add(new DataTable("Setting"));

            m_table = m_data.Tables[0];

            if (!m_table.Columns.Contains("property"))
            {
                DataColumn p = new DataColumn("property");
                p.DataType = typeof(string);
                m_table.Columns.Add(p);
            }
            if (!m_table.Columns.Contains("value"))
            {
                DataColumn v = new DataColumn("value");
                v.DataType = typeof(string);
                m_table.Columns.Add(v);
            }
        }

        /// <summary>
        /// Save Usersettings to file.
        /// </summary>
        public void SaveSettings()
        {
            //m_data.WriteXml(m_fileName);
			saveEncryptedFile(m_fileName, m_data);
        }

        /// <summary>
        /// Save Usersettings to file.
        /// </summary>
        public void SaveSettingsAs(string fileName)
        {
            m_fileName = fileName;
            SaveSettings();
        }

        /// <summary>
        /// Should changes be saved automatically.
		/// </summary>
		public bool Autosave
		{
            get { return m_autosave; }
            set { m_autosave = value; }
        }

        /// <summary>
        /// Should changes be saved automatically.
        /// </summary>
        public string SettingsName
        {
            get { return m_data.DataSetName; }
            set { m_data.DataSetName = value; }
        }

        /// <summary>
        /// Get the Path of the settings file.
        /// </summary>
        public string SettingsPath
        {
            get { return m_fileName; }
        }

        /// <summary>
        /// Get and set the UserSettings as DataSet.
        /// </summary>
        public DataSet Settings
        {
            get { return m_data; }
            set { m_data = value; }
        }

        /// <summary>
        /// Create an Usersettings instance.
        /// </summary>
        public UserSettings()
        {
            m_data = new DataSet();
        }

        /// <summary>
        /// Create an Usersettings instance. Load Settings from file.
        /// </summary>
        /// <param name="fileName">Filename.</param>
        public UserSettings(string fileName)
        {
            m_data = new DataSet();
            LoadSettings(fileName);
		}

		#region File En/Decryption

		// Encryption Key / IV

		private void saveEncryptedFile(string fileName, DataSet settings)
		{
		    byte[] KEY = 
			new byte[] { 0x69, 0x26, 0x5a, 0x33, 0xf, 0xae, 0xbb, 0xb3, 0xda, 0xf8,
						 0xf3, 0xa7, 0xd9, 0xcc, 0xb4, 0xea, 0x11, 0x10, 0xe, 0x43,
						 0x66, 0x19, 0x2a, 0x99, 0x13, 0xe, 0xea, 0xa3, 0x7d, 0x69,
						 0xee, 0x24 };
		    byte[] IV = 
			new byte[] { 0x57, 0xd0, 0x8d, 0xf8, 0x1d, 0x1f, 0xb4, 0xcd, 0x24, 0xf0,
						 0xfd, 0xbb, 0x18, 0x28, 0x29, 0xe1 };

			using (FileStream fsenc = 
					new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Read)) {
				RijndaelManaged myRijndael = new RijndaelManaged();
				//Get an encryptor.
				ICryptoTransform encryptor = myRijndael.CreateEncryptor(KEY, IV);
				//Encrypt the data.
				CryptoStream csEncrypt = new CryptoStream(fsenc, encryptor, CryptoStreamMode.Write);
				settings.WriteXml(csEncrypt);
				csEncrypt.FlushFinalBlock();
				fsenc.Close();
			}
		}
		private DataSet loadEncryptedFile(string fileName)
        {
            byte[] KEY =
            new byte[] { 0x69, 0x26, 0x5a, 0x33, 0xf, 0xae, 0xbb, 0xb3, 0xda, 0xf8,
						 0xf3, 0xa7, 0xd9, 0xcc, 0xb4, 0xea, 0x11, 0x10, 0xe, 0x43,
						 0x66, 0x19, 0x2a, 0x99, 0x13, 0xe, 0xea, 0xa3, 0x7d, 0x69,
						 0xee, 0x24 };
            byte[] IV =
            new byte[] { 0x57, 0xd0, 0x8d, 0xf8, 0x1d, 0x1f, 0xb4, 0xcd, 0x24, 0xf0,
						 0xfd, 0xbb, 0x18, 0x28, 0x29, 0xe1 };
            
			DataSet settings = new DataSet();
			using (FileStream fsdec =
					new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) {
				RijndaelManaged myRijndael = new RijndaelManaged();
				//Get a decryptor.
				ICryptoTransform decryptor = myRijndael.CreateDecryptor(KEY, IV);
				//Decrypt the data.
				CryptoStream csDecrypt = new CryptoStream(fsdec, decryptor, CryptoStreamMode.Read);
				settings.ReadXml(csDecrypt);
			}
			return settings;
		}

		#endregion
	}
}
